#!/usr/bin/env python

#Copyright (C) 2008 Luis Felipe Millani (lf.millani@gmail.com)

#This file is part of MagicLyrics.

#MagicLyrics is free software: you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation, either version 3 of the License, or
#(at your option) any later version.

#MagicLyrics is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.

#You should have received a copy of the GNU General Public License
#along with MagicLyrics.  If not, see <http://www.gnu.org/licenses/>.
from threading import Thread
from time import sleep


class __T(Thread):
	def __init__(self,func,args=(),kwargs={}):
		Thread.__init__(self)
		self.func=func
		self.args=args
		self.kwargs=kwargs
		self.ret_val=None
		self.start()
	def run(self):
		try:
			if self.args==():
				self.ret_val=self.func()
			else:
				self.ret_val=self.func(*self.args,**self.kwargs)
		except:pass

def batch(function,args,kwargs=[],max_threads=0):
	"""
	run function len(args) times, using args[n] as the arguments
	(kwargs[n] too) with a maximum of max_threads threads
	if max_threads==0 then max_threads will be set to cpu_count
	if max_threads<=-1 then it'll be unlimited
	"""
	def launch(i):
		if type(args[i]) in (type([]),type((None,))):
			t_args=tuple(args[i])
		else:
			t_args=(args[i],)
		if i<len(kwargs):
			t_kwargs=kwargs[i]
		else:
			t_kwargs={}
		return __T(function,t_args,t_kwargs),i
	if max_threads<=0:
		max_threads=None
	todo=[]
	ret_vals=[]
	for i in xrange(len(args)):ret_vals.append(None)
	for i in xrange(len(args)):
		while len(todo)==max_threads:
			for t in todo:
				if not t[0].isAlive():
					ret_vals[t[1]]=t[0].ret_val
					todo.remove(t)
			sleep(0.01) # TODO fix this
		todo.append(launch(i))
	for t in todo:
		t[0].join()
		ret_vals[t[1]]=t[0].ret_val
	return ret_vals